介紹完變數後,來看看變數所處的環境。
用最簡單的方式來說,所謂的作用域可以理解為「變數能夠存活的區塊泡泡」。每個變數只屬於一個作用域,一個作用域內則可以存在多個變數。
執行程式時,通常會有複數個作用域同時存在。每個作用域內的程式碼,分別依循該作用域的查找規則存取變數。
程式只能對合法、有開放的作用域進行變數的取值和賦值,如果在當前有效的作用域範圍中無法找到對應變數,程式就會回報 ReferenceError
,表示作用域解析失敗。
作用域主要分成以下兩種:
以下分別詳述:
JavaScript 中的
with
和eval()
能夠修改詞法作用域,達成動態作用域的效果,但由於修改詞法作用域會導致編譯時的最佳化,如靜態分析等失效,造成效能降低問題。因此with
目前已被廢除,而eval()
在 MDN 文件中被強烈建議不要使用。
JavaScript 所採用的是詞法作用域,因此之後的討論都屬於詞法作用域的範疇。
JavaScript 「沒有」動態作用域,但
this
的作用域取決於函式的調用方式,其查找規則擁有與動態作用域相似的機制。
{}
所包覆的區域範圍)可以擁有自己的作用域(ES6+)global
{}
以內的區塊,如 if
、while
、for
等var
沒有區塊作用域,因此定義變數時需要使用 let
或 const
有部分觀點認為,除了通用的常數與少數例外,由於使用困難、不易維護等原因,Global Scope 內不應該存在任何自訂變數。
由於
var
沒有區塊作用域,有時會意外導致變數洩露到外層作用域,因此也有人提倡全面廢止var
,僅使用let
和const
。
用簡單的概念來理解,作用域就是「能夠存取變數的範圍」,不過實際執行時要更複雜一些,用更加嚴謹的方式來說:
「作用域是指一組變數的集合,以及這些變數該如何被查找的規則。」
這些規則與判斷讓程式知道該如何存取變數,從而建構出我們所理解的「作用域」。
而與 JS 作用域相關的規則,則會在後續的文章中一一解析。